#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

typedef int (*process)(void *arg);

int fd[2];

pid_t create_process(process entry, void *arg)
{
	int exit_value;
	pid_t pid;
	
	if(!entry)
		return -1;
	
	//创建子进程
	pid = fork();
	if(pid == 0)
	{
		//fork在子进程中返回0
		exit_value = entry(arg);
		exit(exit_value);
	}
	//fork在父进程中返回子进程的ID
	return pid;
}

int read_process(void *arg)
{
	ssize_t lenght;
	char buffer[100];
	
	//关闭写端
	if(close(fd[1]) == -1)
	{
		perror("close");
		return -1;
	}
	
	while(1)
	{
		//从管道读数据
		memset(buffer, 0, sizeof(buffer));
		lenght = read(fd[0], buffer, sizeof(buffer)-1);
		
		//写端关闭且管道空
		if(lenght == 0)
		{
			//关闭读端
			if(close(fd[0]) == -1)
			{
				perror("close");
				return -1;
			}
			break;
		}
		
		//读取出错
		if(lenght == -1)
		{
			perror("read");
			if(close(fd[0]) == -1)
				perror("close");
			return -1;
		}
		
		//读取成功
		if(lenght > 0)
			printf("%s", buffer);
	}
}

int write_process(void *arg)
{
	int i;
	size_t lenght;
	char buffer[100];
	
	//忽略管道破裂信号
	if(signal(SIGPIPE, SIG_IGN) == SIG_ERR)
	{
		perror("signal");
		return -1;
	}
	
	//关闭读端
	if(close(fd[0]) == -1)
	{
		perror("close");
		return -1;
	}
	
	i = 0;
	while(1)
	{
		i++;
		lenght = snprintf(buffer, sizeof(buffer), "pipe test %d\r\n", i);
		if(write(fd[1], buffer, lenght) == -1)
		{
			perror("write");
			if(close(fd[0]) == -1)
				perror("close");
			break;
		}
		sleep(1);
	}
}

int main(int argv, char *argc[])
{
	pid_t pid1,pid2,pid3;
	
	//在创建子进程前创建管道
	if(pipe(fd) == -1)
	{
		perror("pipe");
		return -1;
	}
	
	//同时创建的进程其执行的先后顺序不确定
	pid1 = create_process(read_process, "read_process;");
	printf("read_process PID=%d\r\n", pid1);
	
	pid2 = create_process(write_process, "write_process;");
	printf("write_process PID=%d\r\n", pid2);
	
	while(1)
	{
		sleep(10);
	}
}
